package org.loong.crypto.service.core.provider.impl;

import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import org.loong.crypto.core.algorithm.SignatureAlgorithm;

/**
 * The base abstract class for RSA signers and verifiers.
 * 
 * <p>
 * Supports the following algorithms:
 *
 * <ul>
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#MD2_RSA}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#MD5_RSA}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA1_RSA}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA224_RSA}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA256_RSA}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA384_RSA}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA512_RSA}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA256_RSASSA_PSS}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA384_RSASSA_PSS}
 * <li>{@link org.loong.crypto.core.algorithm.SignatureAlgorithm#SHA512_RSASSA_PSS}
 * </ul>
 */
public abstract class RSAProvider extends BaseSignatureProvider {

    /**
     * The supported signature algorithms by the RSA provider class.
     */
    public static final Set<SignatureAlgorithm> SUPPORTED_ALGORITHMS;

    static {
        Set<SignatureAlgorithm> algs = new LinkedHashSet<>();
        algs.add(SignatureAlgorithm.MD2_RSA);
        algs.add(SignatureAlgorithm.MD5_RSA);
        algs.add(SignatureAlgorithm.SHA1_RSA);
        algs.add(SignatureAlgorithm.SHA224_RSA);
        algs.add(SignatureAlgorithm.SHA256_RSA);
        algs.add(SignatureAlgorithm.SHA384_RSA);
        algs.add(SignatureAlgorithm.SHA512_RSA);
        algs.add(SignatureAlgorithm.SHA256_RSASSA_PSS);
        algs.add(SignatureAlgorithm.SHA384_RSASSA_PSS);
        algs.add(SignatureAlgorithm.SHA512_RSASSA_PSS);
        SUPPORTED_ALGORITHMS = Collections.unmodifiableSet(algs);
    }

    /**
     * Creates a new RSA provider.
     */
    protected RSAProvider() {
        super(SUPPORTED_ALGORITHMS);
    }

    /**
     * Returns a parameter spec for RSASSA-PSS signature scheme.
     *
     * @param algorithm The algorithm. Must be supported and not {@code null}.
     * @return the parameter spec for RSASSA-PSS signature scheme.
     */
    public PSSParameterSpec getPSSParameterSpec(final SignatureAlgorithm algorithm) {
        PSSParameterSpec pssSpec = null;
        if (algorithm.equals(SignatureAlgorithm.SHA256_RSASSA_PSS)) {
            pssSpec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
        } else if (algorithm.equals(SignatureAlgorithm.SHA384_RSASSA_PSS)) {
            pssSpec = new PSSParameterSpec("SHA-384", "MGF1", MGF1ParameterSpec.SHA384, 48, 1);
        } else if (algorithm.equals(SignatureAlgorithm.SHA512_RSASSA_PSS)) {
            pssSpec = new PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, 1);
        }
        return pssSpec;
    }
}
